Исследование рынка заведений общественного питания Москвы

Оглавление

Описание проекта

В Москве открывается небольшое кафе. Оно оригинальное — гостей должны обслуживать роботы. Инвесторов интересует текущее положение дел на рынке, подтверждающее потенциально высокую популярность идеи и востребованность проекта в долгосрочном периоде.

Цель и задачи проекта

Цель проекта - провести исследование рынка на основе открытых данных о заведениях общественного питания в Москве, дать рекомендации о виде заведения, количестве посадочных мест, а также районе расположения, прокомментировать возможность развития сети.

Для этого необходимо:

  1. исследовать соотношение видов объектов общественного питания по количеству;
  2. исследовать соотношение сетевых и несетевых заведений по количеству;
  3. определить, для какого вида объекта общественного питания характерно сетевое распространение;
  4. определить, что характерно для сетевых заведений: много заведений с небольшим числом посадочных мест в каждом или мало заведений с большим количеством посадочных мест;
  5. для каждого вида объекта общественного питания описать среднее количество посадочных мест, определить, какой вид предоставляет в среднем самое большое количество посадочных мест;
  6. выделить информацию об улице объекта общественного питания;
  7. построить график топ-10 улиц по количеству объектов общественного питания, воспользовавшись внешней информацией, определить, в каких районах Москвы находятся эти улицы;
  8. найти число улиц с одним объектом общественного питания, воспользовавшись внешней информацией, определить, в каких районах Москвы находятся эти улицы;
  9. посмотреть на распределение количества посадочных мест для улиц с большим количеством объектов общественного питания;
  10. подготовить презентацию исследования для инвесторов.

Описание данных

  • id - идентификатор объекта;
  • object_name - название объекта общественного питания;
  • chain - сетевой ресторан;
  • object_type - тип объекта общественного питания;
  • address - адрес;
  • number - количество посадочных мест.

Открытие данных и изучение общей информации

In [1]:
# импортируем необходимые библиотеки
import pandas as pd
import numpy as np
import plotly
import plotly.express as px 
from plotly import graph_objects as go
import plotly.io as pio
pio.templates.default = 'seaborn'
import requests
from io import BytesIO
pd.options.display.float_format = '{:,.2f}'.format
In [2]:
# %%HTML
# <style type="text/css">
# table.dataframe td, table.dataframe th {
#     border: 1px  black solid !important;
#   color: black !important;
# }
In [3]:
# прочитаем DataFrame
try:
    df = pd.read_csv('rest_data.csv')  # локальный путь
except:
    df = pd.read_csv('/datasets/rest_data.csv')  # путь на сервере
In [4]:
# выведем на экран таблицу 10 случайных строк таблицы
df.sample(10)
Out[4]:
id object_name chain object_type address number
11163 178414 Индийская кухня нет кафе город Москва, Открытое шоссе, дом 9, строение 14А 8
6012 141388 Озгон нет кафе город Москва, Краснодарская улица, дом 72, кор... 45
4176 150827 ГБОУ Школа №498 нет столовая город Москва, улица Малые Каменщики, дом 18 0
3225 27487 ГБОУ Школа № 1598 нет столовая город Москва, Камчатская улица, дом 10 230
584 22636 Де Марко да кафе город Москва, Ленинский проспект, дом 13 120
2490 21154 Столовая «Тринта» нет столовая город Москва, Загородное шоссе, дом 2А 24
11848 189893 КСН нет предприятие быстрого обслуживания город Москва, Старокачаловская улица, владение 5А 12
12297 200142 COFFEE SOVA нет кафе город Москва, улица Декабристов, дом 11 6
15084 214843 CoffeeShop да ресторан город Москва, Кутузовский проспект, дом 57 0
1688 151304 Блонд-Брюн нет бар город Москва, 1-я улица Машиностроения, дом 10 35
In [5]:
# посмотрим сводную информацию таблицы
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 15366 entries, 0 to 15365
Data columns (total 6 columns):
 #   Column       Non-Null Count  Dtype 
---  ------       --------------  ----- 
 0   id           15366 non-null  int64 
 1   object_name  15366 non-null  object
 2   chain        15366 non-null  object
 3   object_type  15366 non-null  object
 4   address      15366 non-null  object
 5   number       15366 non-null  int64 
dtypes: int64(2), object(4)
memory usage: 720.4+ KB

В таблице 15366 строк, 6 столбцов, тип данных у четырех столбцов строковый, у двух - целочисленный.

Столбец id

In [6]:
# посмотрим количество уникальных значений в столбце
df['id'].value_counts()
Out[6]:
27662     1
223307    1
185071    1
23278     1
21451     1
         ..
155041    1
21920     1
107934    1
26006     1
163840    1
Name: id, Length: 15366, dtype: int64

В таблице представлена информация по 15366 уникальным объектам общественного питания.

Столбец object_name

In [7]:
# посмотрим количество уникальных значений в столбце
df['object_name'].value_counts()
Out[7]:
Столовая                     267
Кафе                         236
Шаурма                       234
KFC                          155
Шоколадница                  142
                            ... 
КАФЕ -БАР «Кипарис»            1
Кафе «ARCUS BAR and FOOD»      1
Кафе «Кафейня»                 1
Столовая ГОУ КАМС №17          1
Ресторан «СОЗВЕЗДИЕ»           1
Name: object_name, Length: 10393, dtype: int64

Уникальных названий объектов - 10393. Больше всего объектов с обезличенными названиями - "Столовая" - 267, "Кафе" - 236, "Шаурма" - 234. Кроме того одинаковые названия у объектов из одной сети.

Проверим имеются ли одинаковые названия у сетевых и несетевых объектов.

In [8]:
# создадим таблицу с объектами, имеющими одинаковые названия и относящимися к разным типам
chain_joint = df.pivot_table(index = 'object_name',
                             columns = 'chain',
                             values = 'id',
                             aggfunc = 'count')\
                .reset_index()
chain_joint = chain_joint[(chain_joint['да'].notnull()) & (chain_joint['нет'].notnull())]
chain_joint
Out[8]:
chain object_name да нет
429 FRIDAYS 1.00 2.00
529 Goodman Гудман 1.00 1.00
1283 Tutti frutti 1.00 1.00
1285 UPSIDE DOWN CAKE 1.00 1.00
1289 Upside Down Cake 1.00 2.00
1469 Азбука Вкуса 5.00 4.00
1470 Азбука вкуса 2.00 4.00
2421 Виктория 1.00 1.00
2866 Готовые блюда Милти 1.00 1.00
3838 Кальянная Мята Lounge 1.00 3.00
4098 Кафе «Subway» 2.00 1.00
4573 Кафе «Хинкальная» 3.00 6.00
4617 Кафе «Шоколадница» 14.00 2.00
4619 Кафе «Штолле» 2.00 1.00
4905 Кафе при АЗС 1.00 4.00
5141 Колбасофф 1.00 2.00
5195 Кондитерская-пекарня Волконский 2.00 1.00
5228 Кофе 1.00 15.00
5623 Лукойл 1.00 2.00
6008 Мята 1.00 7.00
6628 Пицца «Паоло» 1.00 1.00
7107 Ресторан «KFC» 2.00 1.00
7197 Ресторан «Бургер Кинг» 1.00 1.00
7391 Ресторан «Хинкальная» 1.00 1.00
7418 Ресторан «Якитория» 1.00 1.00
9188 Темпл Бар 1.00 1.00
9195 Теремок-Инвест 1.00 1.00
10207 Шоколадница 141.00 1.00
10327 Япоша 1.00 1.00
In [9]:
# посчитаем количество объектов, имеющих одинаковые названия и относящихся к разным типам
len(chain_joint)
Out[9]:
29

Имеется 29 названий объектов, которые относятся к сетевым, но в то же время использующиеся и несетевыми заведениями. Возможно, это ошибка в имеющейся информации, однако может быть и нелегальное использование названий сетевых объектов. Учитывая имеющуюся неопределенность, оставим данное положение без изменений.

Столбец chain

In [10]:
# посмотрим количество уникальных значений в столбце
df['chain'].value_counts()
Out[10]:
нет    12398
да      2968
Name: chain, dtype: int64

Сетевых объектов 2968, несетевых - 12398. Для упрощения можно заменить значения "да" на "chain", а "нет" - на "not_chain".

Столбец object_type

In [11]:
# посмотрим количество уникальных значений в столбце
df['object_type'].value_counts()
Out[11]:
кафе                                 6099
столовая                             2587
ресторан                             2285
предприятие быстрого обслуживания    1923
бар                                   856
буфет                                 585
кафетерий                             398
закусочная                            360
магазин (отдел кулинарии)             273
Name: object_type, dtype: int64

Имеется информация по 9 типам объектов общественного питания. По типам объектов наибольшее количество кафе - 6099, наименьшее - отделов кулинарии - 273. Для упрощения можно заменить длинные названия типов объектов на короткие: соответственно "предприятие быстрого обслуживания" на "фаст-фуд", а "магазин (отдел кулинарии)" на "кулинария".

Столбец address

In [12]:
# посмотрим количество уникальных значений в столбце
df['address'].value_counts()
Out[12]:
город Москва, Ходынский бульвар, дом 4                 95
город Москва, Пресненская набережная, дом 2            63
город Москва, проспект Мира, дом 211, корпус 2         60
город Москва, Кировоградская улица, дом 13А            53
город Москва, площадь Киевского Вокзала, дом 2         48
                                                       ..
город Москва, Киевская улица, дом 7, корпус 1           1
город Москва, Севастопольский проспект, дом 6           1
город Москва, улица Серпуховский Вал, дом 14            1
город Москва, Автозаводская улица, дом 16, корпус 2     1
город Москва, Ясный проезд, дом 10, корпус 3            1
Name: address, Length: 9108, dtype: int64

Заведения расположены по 9108 адресам, т.е. имеется множество объектов, расположенных по одному адресу. Вероятнее всего, это крупные торговые центры. Наибольшее количество объектов общественного питания расположено по адресу: город Москва, Ходынский бульвар, дом 4, - 95. Для дальнейшего исследования необходимо у значений заменить букву "ё" на букву "е".

Проверим, имеются ли объекты с одинаковым названием, располагающиеся по одному и тому же адресу.

In [13]:
# создадим таблицу с объектами, имеющими одинаковые названия и располагающимися по одному и тому же адресу
address_joint = df.pivot_table(index = ['address', 'object_name'],
                               values = 'id',
                               aggfunc = 'count')\
                  .reset_index()\
                  .sort_values(by = 'id',
                              ascending = False)
address_joint = address_joint.query('id > 1')
address_joint
Out[13]:
address object_name id
386 город Москва, 2-я Бауманская улица, дом 5, стр... КОМБИНАТ ПИТАНИЯ МГТУ ИМ.Н.Э.БАУМАНА 11
217 город Москва, 1-я Останкинская улица, дом 55 Кафе 9
9629 город Москва, Шарикоподшипниковская улица, дом... Лиор 8
8958 город Москва, Тихорецкий бульвар, владение 1, ... Кафе 6
1082 город Москва, Багратионовский проезд, дом 7, к... LIFT 6
... ... ... ...
5253 город Москва, Манежная площадь, дом 1, строение 2 IL PATIO 2
8680 город Москва, Сходненская улица, дом 37 Zotto 2
7043 город Москва, Пресненская набережная, дом 2 Starbucks 2
6616 город Москва, Открытое шоссе, дом 9, строение 14А Дагестанская кухня 2
7548 город Москва, Пятницкое шоссе, дом 18 Шаурма 2

137 rows × 3 columns

Имеется 137 заведений, имеющих одинаковые названия и располагающихся по одному и тому же адресу. В основном это объекты с обезличенными названиями, кроме того, вероятно, могут открываться одинаковые объекты при избыточном спросе, а также в учебных заведениях с большим количеством корпусов.

Столбец number

In [14]:
# посмотрим количество уникальных значений в столбце
df['number'].value_counts()
Out[14]:
0      1621
40      835
20      727
30      685
10      644
       ... 
491       1
675       1
455       1
167       1
495       1
Name: number, Length: 315, dtype: int64

У 1621 объекта общественного питания отсутствуют посадочные места. Вероятнее всего, это небольшие заведения по размеру, предлагающие блюда на вынос. Для удобства можно поменять название столбца.

In [15]:
# проведем базовую проверку столбца
df['number'].describe()
Out[15]:
count   15,366.00
mean        59.55
std         74.74
min          0.00
25%         12.00
50%         40.00
75%         80.00
max      1,700.00
Name: number, dtype: float64

Среднее количество посадочных мест - около 60, максимальное - 1700. Половина всех объектов общественного питания имеет до 40 посадочных мест.

In [16]:
# посмотрим на самые большие объекты общественного питания
df.query('number >= 1000')
Out[16]:
id object_name chain object_type address number
2313 26560 Ресторан «АЛЬФА» нет ресторан город Москва, Измайловское шоссе, дом 71, корп... 1040
3686 27026 РУМ СЕРВИС нет ресторан город Москва, площадь Европы, дом 2 1200
4480 27024 РУМ СЕРВИС нет ресторан город Москва, Кутузовский проспект, дом 2/1, с... 1200
8148 80291 Банкетный зал Шелк нет ресторан город Москва, Большой Саввинский переулок, дом... 1500
8345 27750 СТОЛОВАЯ-БУФЕТ нет столовая город Москва, улица Волхонка, дом 15 1400
9064 19719 КОМБИНАТ ПИТАНИЯ «УПРАВЛЕНИЕ АКАДЕМСЕРВИС» нет столовая город Москва, проспект Вернадского, дом 84, ст... 1288
12723 199696 Arena by Soho Family нет бар город Москва, Кутузовский проспект, дом 36, ст... 1700

Имеется 7 заведений, у которых количество посадочных мест более 1000.

In [17]:
# определим количество пропущенных значений в таблице
df.isnull().sum()
Out[17]:
id             0
object_name    0
chain          0
object_type    0
address        0
number         0
dtype: int64

Пропущенные значения отсутствуют.

In [18]:
# посчитаем количество дубликатов
df.duplicated().sum()
Out[18]:
0

Дубликаты отсутствуют.

Вывод

При изучении таблицы с данными установлено, что в ней 15366 строк, 6 столбцов, тип данных у четырех столбцов строковый, у двух - целочисленный, пропущенные значения и дубликаты отсутствуют. Кроме того:

  1. Столбец id:
    • в таблице представлена информация по 15366 уникальным объектам общественного питания.
  2. Столбец object_name:
    • уникальных названий объектов - 10393;
    • больше всего объектов с обезличенными названиями - "Столовая" - 267, "Кафе" - 236, "Шаурма" - 234, кроме того одинаковые названия у объектов из одной сети;
    • имеется 29 названий объектов, которые относятся к сетевым, но в то же время использующиеся и несетевыми заведениями. Возможно, это ошибка в имеющейся информации, однако может быть и нелегальное использование названий сетевых объектов. Учитывая имеющуюся неопределенность, оставим данное положение без изменений.
  3. Столбец chain:
    • сетевых объектов 2968, несетевых - 12398;
    • для упрощения можно заменить значения "да" на "chain", а "нет" - на "not_chain".
  4. Столбец object_type:
    • имеется информация по 9 типам объектов общественного питания;
    • по типам объектов наибольшее количество кафе - 6099, наименьшее - отделов кулинарии - 273;
    • для упрощения можно заменить длинные названия типов объектов на короткие: соответственно "предприятие быстрого обслуживания" на "фаст-фуд", а "магазин (отдел кулинарии)" на "кулинария".
  5. Столбец address:
    • заведения расположены по 9108 адресам, т.е. имеется множество объектов, расположенных по одному адресу, вероятнее всего, это крупные торговые центры;
    • наибольшее количество объектов общественного питания расположено по адресу: город Москва, Ходынский бульвар, дом 4, - 95;
    • для дальнейшего исследования необходимо у значений заменить букву "ё" на букву "е";
    • имеется 137 заведений, имеющих одинаковые названия и располагающихся по одному и тому же адресу. В основном это объекты с обезличенными названиями, кроме того, вероятно, могут открываться одинаковые объекты при избыточном спросе, а также в учебных заведениях с большим количеством корпусов.
  6. Столбец number:
    • у 1621 объекта общественного питания отсутствуют посадочные места, вероятнее всего, это небольшие заведения по размеру, предлагающие блюда на вынос;
    • для удобства можно поменять название столбца;
    • среднее количество посадочных мест - около 60, максимальное - 1700, половина всех объектов общественного питания имеет до 40 посадочных мест;
    • имеется 7 заведений, у которых количество посадочных мест более 1000.

Проанализировав вышеизложенное, необходимо выполнить следующее:

  1. заменить значения в столбце chain на "chain" и "not_chain";
  2. заменить длинные названия типов объектов в столбце object_type на короткие;
  3. у значений в столбце address заменить букву "ё" на букву "е";
  4. поменять название столбца number.

Подготовка данных

In [19]:
# заменим значения в столбце отношения объекта к сетевым 
df['chain'] = df['chain'].map({'нет': 'not_chain','да': 'chain'})
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 15366 entries, 0 to 15365
Data columns (total 6 columns):
 #   Column       Non-Null Count  Dtype 
---  ------       --------------  ----- 
 0   id           15366 non-null  int64 
 1   object_name  15366 non-null  object
 2   chain        15366 non-null  object
 3   object_type  15366 non-null  object
 4   address      15366 non-null  object
 5   number       15366 non-null  int64 
dtypes: int64(2), object(4)
memory usage: 720.4+ KB
In [20]:
# заменим длинные названия типов объектов на короткие
df['object_type'] = df['object_type'].replace('предприятие быстрого обслуживания', 'фаст-фуд')
df['object_type'] = df['object_type'].replace('магазин (отдел кулинарии)', 'кулинария')
df['object_type'].unique()
Out[20]:
array(['кафе', 'столовая', 'закусочная', 'фаст-фуд', 'ресторан',
       'кафетерий', 'буфет', 'бар', 'кулинария'], dtype=object)
In [21]:
# заменим букву "ё" на букву "е" в столбце с адресом объекта
df['address'] = df['address'].str.replace('ё', 'е')
In [22]:
# поменяем название столбца 'number'
df = df.rename(columns = {'number':'number_of_seats'})
df.columns
Out[22]:
Index(['id', 'object_name', 'chain', 'object_type', 'address',
       'number_of_seats'],
      dtype='object')

В целях подготовки данных провели следующую работу:

  1. заменили значения в столбце chain на "chain" и "not_chain";
  2. заменили длинные названия типов объектов в столбце object_type на короткие;
  3. у значений в столбце address заменили букву "ё" на букву "е";
  4. поменяли название столбца number.

Исследование данных

Анализ соотношения видов объектов общественного питания по количеству

In [23]:
# содадим таблицу с количеством объектов общественного питания по видам
object_count_type = df.groupby('object_type')\
                      .agg({'id': 'count'})\
                      .reset_index()\
                      .rename(columns = {'id' : 'count'})\
                      .sort_values(by = 'count',
                                   ascending = False)\
                      .reset_index(drop = True)
object_count_type
Out[23]:
object_type count
0 кафе 6099
1 столовая 2587
2 ресторан 2285
3 фаст-фуд 1923
4 бар 856
5 буфет 585
6 кафетерий 398
7 закусочная 360
8 кулинария 273
In [24]:
# построим график количества объектов общественного питания по видам
fig = px.bar(object_count_type,
             x = 'object_type',
             y = 'count',
             color = 'object_type')
fig.update_layout(title = 'Количество объектов общественного питания по видам',
                  xaxis_title = 'Вид объекта',
                  yaxis_title = 'Количество объектов',
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 20))
fig.update_traces(hovertemplate = 'Вид: %{x}<br>Количество: %{y}')
fig.show()
In [25]:
# построим график соотношения объектов общественного питания по видам
fig = go.Figure()
fig.add_trace(go.Pie(labels = object_count_type['object_type'],
                     values = object_count_type['count'],
                     hole = 0.55))
fig.update_layout(annotations = [dict(text = 'Соотношение объектов<br>общественного питания<br>по видам',
                                      font_size = 20,
                                      showarrow = False)],
                  legend = dict(x = 0.78,
                                font_size = 16),
                  margin = dict(l = 0, r = 0, t = 20, b = 20))
fig.update_traces(textposition = 'inside',
                  textfont_size = 16)
fig.show()

В Москве самым популярным видом объекта общественного питания является кафе - имеется 6099 таких заведений (39,7% от общего количества объектов). Достаточно большую долю на рынке занимают столовые, рестораны и предприятия быстрого обслуживания (фаст-фуды), которая составляет соответственно 16,8% (2587 заведений), 14,9% (2285 заведений) и 12,5% (1923 заведения). Менее 3% доля от общего количества объектов у отделов кулинарий магазинов, закусочных и кафетериев.

Анализ соотношения сетевых и несетевых заведений по количеству

In [26]:
# содадим таблицу с количеством объектов общественного питания по отношению к сетевым
object_count_chain = df.groupby('chain')\
                       .agg({'id': 'count'})\
                       .reset_index()\
                       .rename(columns = {'id' : 'count'})\
                       .sort_values(by = 'count',
                                   ascending = False)\
                       .reset_index(drop = True)
object_count_chain['chain'] = object_count_chain['chain'].map({'not_chain': 'несетевой','chain': 'сетевой'})
object_count_chain
Out[26]:
chain count
0 несетевой 12398
1 сетевой 2968
In [27]:
# построим график количества объектов общественного питания по отношению к сетевым
fig = px.bar(object_count_chain,
             x = 'chain',
             y = 'count',
             color = 'chain')
fig.update_layout(title = 'Количество объектов общественного питания по отношению к сетевым',
                  xaxis_title = 'Тип объекта',
                  yaxis_title = 'Количество объектов',
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Тип: %{x}<br>Количество: %{y}')
fig.show()
In [28]:
# построим график соотношения объектов общественного питания по отношению к сетевым
fig = go.Figure()
fig.add_trace(go.Pie(labels = object_count_chain['chain'],
                     values = object_count_chain['count'],
                     hole = 0.55))
fig.update_layout(annotations = [dict(text = 'Соотношение объектов<br>общественного питания<br>по отношению к сетевым',
                                      font_size = 18,
                                      showarrow = False)],
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 20, b = 20))
fig.update_traces(textposition = 'inside',
                  textinfo = 'percent + label',
                  textfont_size = 16)
fig.show()

В Москве преобладают несетевые объекты общественного питания, их доля от общего количества заведений составляет 80,7% (количество - 12398). Объектов, принадлежащих различным сетям, 2968 (19,3%).

Определение, для какого вида объекта общественного питания характерно сетевое распространение

In [29]:
# создадим таблицу с количеством объектов общественного питания по отношению к сетевым по видам
object_count_type_chain = df.pivot_table(index = 'object_type',
                                         columns = 'chain',
                                         values = 'id',
                                         aggfunc = 'count')\
                            .sort_values(by = 'chain',
                                         ascending = False)\
                            .reset_index()                     
object_count_type_chain                            
Out[29]:
chain object_type chain not_chain
0 кафе 1396 4703
1 фаст-фуд 791 1132
2 ресторан 544 1741
3 кулинария 78 195
4 закусочная 56 304
5 кафетерий 52 346
6 бар 37 819
7 буфет 11 574
8 столовая 3 2584
In [30]:
# построим график количества объектов общественного питания по отношению к сетевым по видам
fig = go.Figure()
fig.add_trace(go.Bar(x = object_count_type_chain['object_type'],
                     y = object_count_type_chain['chain'],
                     name = 'сетевой'))
fig.add_trace(go.Bar(x = object_count_type_chain['object_type'],
                     y = object_count_type_chain['not_chain'],
                     name = 'несетевой'))
fig.update_layout(title = 'Количество объектов общественного питания по отношению к сетевым по видам',
                  xaxis_title = 'Вид объекта',
                  yaxis_title = 'Количество объектов',
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hoverinfo = 'all', hovertemplate = 'Вид: %{x}<br>Количество: %{y}')
fig.show()

В абсолютном выражении среди сетевых объектов общественного питания больше всего кафе, вероятнее всего из-за большей распространенности заведений этого вида.

In [31]:
# построим график соотношения объектов общественного питания по отношению к сетевым по видам
fig = go.Figure()
fig.add_trace(go.Scatter(x = object_count_type_chain['object_type'],
                         y = object_count_type_chain['chain'],
                         mode = 'lines + markers',
                         name = 'сетевой',
                         stackgroup = 'one',
                         groupnorm = 'percent'))
fig.add_trace(go.Scatter(x = object_count_type_chain['object_type'],
                         y = object_count_type_chain['not_chain'],
                         mode = 'lines',
                         name = 'несетевой',
                         stackgroup = 'one',
                         groupnorm = 'percent'))
fig.update_layout(yaxis = dict(range = [0.1, 100],
                               ticksuffix = '%'),
                  title = 'Соотношение объектов общественного питания по отношению к сетевым по видам',
                  xaxis_title = 'Вид объекта',
                  yaxis_title = 'Доля объектов',
                  legend_orientation = 'h',
                  margin = dict(l = 0, r = 20, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Вид: %{x}<br>Доля: %{y}')
fig.show()

При изучении относительных показателей картина немного иная. Наибольшая доля сетевых заведений у фаст-фудов (41,1%) и кулинарий (28,6%). У самого распространенного вида объектов общественного питания - кафе - доля сетевых заведений составляет 22,3%. Наименьшее и абсолютное количество сетевых заведений, и доля от всех объектов данного вида у столовых и буфетов.

Определение, что характерно для сетевых заведений: много заведений с небольшим числом посадочных мест в каждом или мало заведений с большим количеством посадочных мест

In [32]:
# посмотрим статистические показатели количества посадочных мест сетевых и несетевых объектов общественного питания
stat_chain = df.query('chain == "chain"')\
               ['number_of_seats'].describe()\
               .reset_index()\
               .rename(columns = {'index' : 'parameter',
                                  'number_of_seats' : 'chain'})
stat_not_chain = df.query('chain == "not_chain"')\
                   ['number_of_seats'].describe()\
                   .reset_index()\
                   .rename(columns = {'index' : 'parameter',
                                      'number_of_seats' : 'not_chain'})
stat_all = stat_chain.merge(stat_not_chain,
                            on = 'parameter')
stat_all
Out[32]:
parameter chain not_chain
0 count 2,968.00 12,398.00
1 mean 52.92 61.13
2 std 57.14 78.28
3 min 0.00 0.00
4 25% 15.00 12.00
5 50% 40.00 40.00
6 75% 72.00 80.00
7 max 580.00 1,700.00

Среднее количество посадочных мест в сетевых объектах общественного питания 53, медианное - 40. Для 75% сетевых заведений число посадочных мест не превысило 72. Для несетевых заведений характерен больший разброс значений количества посадочных мест, при этом при одинаковых медианных значениях количества мест у сетевых и несетевых объектов, среднее арифиметическое у несетевых заведений значительно выше.

In [33]:
# построим график распределения сетевых объектов общественного питания по количеству посадочных мест
fig = px.histogram(df.query('chain == "chain"'),
                   x = 'number_of_seats',
                   marginal = 'box')
fig.update_layout(title = 'Распределение сетевых объектов общественного питания по количеству посадочных мест',
                  xaxis_title = 'Количество посадочных мест',
                  yaxis_title = 'Количество объектов',
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Мест: %{x}<br>Количество: %{y}')
fig.show()

Исходя из построенного графика, можно утверждать, что для сетевых объектов общественного питания Москвы характерно много заведений с небольшим количеством посадочных мест в каждом, и мало заведений с большим числом посадочных мест в каждом.

Описание для каждого вида объекта общественного питания среднего количества посадочных мест, определение, какой вид предоставляет в среднем самое большое количество посадочных мест

In [34]:
# построим график распределения количества посадочных мест по видам объектов общественного питания
fig = px.box(df,
             x = 'object_type',
             y = 'number_of_seats',
             color = 'object_type')
fig.update_layout(title = 'Распределение количества посадочных мест по видам объектов общественного питания',
                  xaxis_title = 'Вид объекта',
                  yaxis_title = 'Количество посадочных мест',
                  yaxis = dict(range = [-10, 400]),
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Вид: %{x}<br>Количество: %{y}')
fig.show()

Для каждого из видов объектов общественного питания характерна следующая закономерность: имеется небольшое количество заведений с большим числом посадочных мест и большое количество объектов с их небольшим числом. Наибольшее количество посадочных мест из видов объектов общественного питания у столовых, у них же наибольший разброс этих значений. У закусочных и кулинарий более половины заведений не имеет посадочных мест, а у кафетериев и фаст-фудов посадочных мест не имеют более 25% объектов.

Учитывая большой разброс значений числа посадочных мест по всем видам объектов общественного питания, средним их количеством будем считать медиану.

In [35]:
# создадим таблицу со средним количеством посадочных мест по видам объектов общественного питания
object_type_seats = df.groupby('object_type')\
                      .agg({'number_of_seats' : 'median'})\
                      .sort_values(by = 'number_of_seats',
                                   ascending = False)\
                      .rename(columns = {'number_of_seats' : 'number_of_seats_mean'})\
                      .reset_index()
object_type_seats
Out[35]:
object_type number_of_seats_mean
0 столовая 103
1 ресторан 80
2 бар 35
3 буфет 32
4 кафе 30
5 кафетерий 6
6 фаст-фуд 5
7 закусочная 0
8 кулинария 0
In [36]:
# построим график среднего количества посадочных мест по видам объектов общественного питания
fig = px.bar(object_type_seats,
             x = 'object_type',
             y = 'number_of_seats_mean',
             color = 'object_type')
fig.update_layout(title = 'Среднее количество посадочных мест по видам объектов общественного питания',
                  xaxis_title = 'Вид объекта',
                  yaxis_title = 'Количество посадочных мест',
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Вид: %{x}<br>Количество: %{y}')
fig.show()

Наибольшее среднее количество посадочных мест у столовых - 103, и ресторанов - 80. У самого распространенного вида заведений - кафе - среднее количество посадочных мест достаточно небольшое - 30. У объектов с самой большой долей сетевых заведений - фаст-фудов - среднее количество посадочных мест совсем мало - 5. У закусочных и кулинарий среднее количество посадочных мест равно 0.

Выделение информации об улице объекта общественного питания

Так как улица размещения объекта общественного питания является одним из важнейших факторов для принятия решения об открытии заведения, необходимо изучить столбец с адресами объектов подробнее, исключив из таблицы строки с заведениями из Зеленограда и населенных пунктов Новой Москвы, в связи с тем, что в них могут быть такие же названия улиц, как и в самой Москве.

In [37]:
# удалим из таблицы строки с заведениями из Зеленограда и населенных пунктов Новой Москвы
for city in ['город Зеленоград',
             'поселение',
             'город Троицк',
             'город Щербинка',
             'город Московский',
             'поселок Внуково',
             'поселок Акулово',
             'деревня Толстопальцево']:
    df = df[~df['address'].apply(lambda x: city in x)]
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 14536 entries, 0 to 15365
Data columns (total 6 columns):
 #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
 0   id               14536 non-null  int64 
 1   object_name      14536 non-null  object
 2   chain            14536 non-null  object
 3   object_type      14536 non-null  object
 4   address          14536 non-null  object
 5   number_of_seats  14536 non-null  int64 
dtypes: int64(2), object(4)
memory usage: 794.9+ KB

Удалили 829 строк, или 5,4%.

In [38]:
# проверим, во всех ли строках столбца с адресом объекта указан город
df[~df['address'].apply(lambda x: 'город Москва' in x)]
Out[38]:
id object_name chain object_type address number_of_seats
859 23601 Буфет - ГБОУ СОШ № 64 not_chain буфет Партизанская улица, дом 30 100
860 23604 Буфет - ГБОУ 60 not_chain буфет Партизанская улица, дом 30 100
1491 25349 Ресторан «Гранатовый сад» not_chain ресторан Поречная улица, дом 5/14, строение 1 40
7691 132359 Кафе «La Carotte» not_chain кафе 1-й Нагатинский проезд, дом 10 198
7827 28214 Роснефть (закрытое) not_chain столовая Софийская набережная, дом 26/1, строение 1 80
... ... ... ... ... ... ...
13184 192903 Сабрина not_chain кафе Бауманская улица, дом 7, строение 3 30
13185 192918 Limassol not_chain кафе Бауманская улица, дом 7, строение 3 42
13399 204788 Крошка Картошка chain фаст-фуд Солянский тупик, дом 1/4, строение 1 15
13991 204917 Шаурма на углях- Чайхана Баракат not_chain кафе Таганская площадь, дом 88, строение 4 80
14003 211986 FRESH CAFE not_chain кафе Шарикоподшипниковская улица, дом 5, строение 1 42

63 rows × 6 columns

Имеется 63 строки, в которых в столбце с адресом объекта общественного питания не указан город.

In [39]:
# добавим город в столбец с адресом объекта общественного питания
df.loc[~df['address'].apply(lambda x: 'город Москва' in x), 'address'] =\
                     'город Москва, ' + df.loc[~df['address'].apply(lambda x: 'город Москва' in x), 'address']
df.loc[~df['address'].apply(lambda x: 'город Москва' in x), 'address']
Out[39]:
Series([], Name: address, dtype: object)
In [40]:
# создадим таблицу с разделением адреса объекта общественного питания на столбцы
address_table = df['address'].str.split(', ', expand = True)
address_table.head()
Out[40]:
0 1 2 3 4 5
0 город Москва улица Егора Абакумова дом 9 None None None
1 город Москва улица Талалихина дом 2/1 корпус 1 None None
2 город Москва Абельмановская улица дом 6 None None None
3 город Москва Абрамцевская улица дом 1 None None None
4 город Москва Абрамцевская улица дом 9 корпус 1 None None

Навание улицы оказалось в столбце 1.

In [41]:
# добавим в таблицу столбец с улицей объекта общественного питания
df['street'] = address_table[1]
df.head()
Out[41]:
id object_name chain object_type address number_of_seats street
0 151635 СМЕТАНА not_chain кафе город Москва, улица Егора Абакумова, дом 9 48 улица Егора Абакумова
1 77874 Родник not_chain кафе город Москва, улица Талалихина, дом 2/1, корпус 1 35 улица Талалихина
2 24309 Кафе «Академия» not_chain кафе город Москва, Абельмановская улица, дом 6 95 Абельмановская улица
3 21894 ПИЦЦЕТОРИЯ chain кафе город Москва, Абрамцевская улица, дом 1 40 Абрамцевская улица
4 119365 Кафе «Вишневая метель» not_chain кафе город Москва, Абрамцевская улица, дом 9, корпус 1 50 Абрамцевская улица

Таким образом, в исходную таблицу добавлен столбец с улицей, на которой размещен объект общественного питания.

Выделение топ-10 улиц по количеству объектов общественного питания, определение, в каких районах Москвы находятся эти улицы

Получим из внешнего источника информацию о принадлежности улиц к районам Москвы. Для уменьшения размера таблицы из нее предварительно были удалены ненужные столбцы.

In [42]:
# выгрузим файл
spreadsheet_id = '1LnuSRFScSIh8fVxsDPgJa4NoXutu7NzNM1lT7RHPAuQ'
file_name = 'https://docs.google.com/spreadsheets/d/{}/export?format=csv'.format(spreadsheet_id) 
r = requests.get(file_name) 
open_data = pd.read_csv(BytesIO(r.content))
open_data.head()
Out[42]:
ADDRESS ADM_AREA DISTRICT
0 город Москва, Варшавское шоссе, дом 150, строе... Южный административный округ муниципальный округ Чертаново Южное
1 город Москва, Косинская улица, дом 26А Восточный административный округ муниципальный округ Вешняки
2 город Москва, Гороховский переулок, дом 21 Центральный административный округ муниципальный округ Басманный
3 город Москва, Тагильская улица, дом 4, строени... Восточный административный округ муниципальный округ Метрогородок
4 город Москва, Ленинградский проспект, дом 73А,... Северный административный округ муниципальный округ Сокол
In [43]:
# приведем названия столбцов к нижнему регистру
open_data.columns = open_data.columns.str.lower()
open_data.head()
Out[43]:
address adm_area district
0 город Москва, Варшавское шоссе, дом 150, строе... Южный административный округ муниципальный округ Чертаново Южное
1 город Москва, Косинская улица, дом 26А Восточный административный округ муниципальный округ Вешняки
2 город Москва, Гороховский переулок, дом 21 Центральный административный округ муниципальный округ Басманный
3 город Москва, Тагильская улица, дом 4, строени... Восточный административный округ муниципальный округ Метрогородок
4 город Москва, Ленинградский проспект, дом 73А,... Северный административный округ муниципальный округ Сокол
In [44]:
# заменим букву "ё" на букву "е" в столбце с адресом объекта
open_data['address'] = open_data['address'].str.replace('ё', 'е')
In [45]:
# добавим в исходную таблицу сведения об административном и муниципальном округах,
# в которых находятся объекты общественного питания
df_new = df.merge(open_data,
                  on = 'address',
                  how = 'left')
df_new.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 14558 entries, 0 to 14557
Data columns (total 9 columns):
 #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
 0   id               14558 non-null  int64 
 1   object_name      14558 non-null  object
 2   chain            14558 non-null  object
 3   object_type      14558 non-null  object
 4   address          14558 non-null  object
 5   number_of_seats  14558 non-null  int64 
 6   street           14558 non-null  object
 7   adm_area         14388 non-null  object
 8   district         14388 non-null  object
dtypes: int64(2), object(7)
memory usage: 1.1+ MB
In [46]:
# посчитаем количество дубликатов
df_new.duplicated().sum()
Out[46]:
22
In [47]:
# удалим дубликаты
df_new = df_new.drop_duplicates().reset_index(drop = True)
df_new.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 14536 entries, 0 to 14535
Data columns (total 9 columns):
 #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
 0   id               14536 non-null  int64 
 1   object_name      14536 non-null  object
 2   chain            14536 non-null  object
 3   object_type      14536 non-null  object
 4   address          14536 non-null  object
 5   number_of_seats  14536 non-null  int64 
 6   street           14536 non-null  object
 7   adm_area         14366 non-null  object
 8   district         14366 non-null  object
dtypes: int64(2), object(7)
memory usage: 1022.2+ KB
In [48]:
# определим долю пропущенных значений в таблице
df_new.isnull().mean() * 100
Out[48]:
id                0.00
object_name       0.00
chain             0.00
object_type       0.00
address           0.00
number_of_seats   0.00
street            0.00
adm_area          1.17
district          1.17
dtype: float64

Не заполнилось 1,2% значений в столбцах административного и муниципального округов объекта общественного питания. Попробуем их заполнить по названию улицы.

In [49]:
# создадим список с улицами, у которых есть незаполненные значения административного и муниципального округов
area_isna = (df_new['adm_area'].isna() == True) & (df_new['district'].isna() == True)
unnamed_streets = df_new.loc[area_isna, 'street'].to_list()
unnamed_streets
Out[49]:
['Партизанская улица',
 'Партизанская улица',
 'Шоссейная улица',
 'Поречная улица',
 'улица Адмирала Лазарева',
 'Глубокий переулок',
 'Глубокий переулок',
 'Пятницкая улица',
 'Гостиничная улица',
 'улица Героев-Панфиловцев',
 'улица Героев-Панфиловцев',
 'Пятницкая улица',
 'Пятницкая улица',
 'Пятницкая улица',
 'Зубовский бульвар',
 'улица Солянка',
 'Славянская площадь',
 'Славянская площадь',
 'Славянская площадь',
 'Славянская площадь',
 'Славянская площадь',
 'Славянская площадь',
 'Новослободская улица',
 'Озерная улица',
 'Полярная улица',
 'улица Плещеева',
 '87-й километр Московской Кольцевой Автодороги',
 'Ярославское шоссе',
 'Суздальская улица',
 'Щелковское шоссе',
 'Русаковская набережная',
 'Угрешская улица',
 'улица Перерва',
 'улица Обручева',
 'улица Дмитрия Ульянова',
 'Старобитцевская улица',
 'Изюмская улица',
 'Чечерский проезд',
 'Старокачаловская улица',
 'Старокачаловская улица',
 'Старокачаловская улица',
 'Старокачаловская улица',
 'Старокачаловская улица',
 'Старокачаловская улица',
 'Старокалужское шоссе',
 'Волоколамское шоссе',
 'Пятницкое шоссе',
 '74-й километр Московской Кольцевой Автодороги',
 'Таманская улица',
 'улица Правды',
 'улица Правды',
 'улица Грузинский Вал',
 'улица Дыбенко',
 'Дмитровское шоссе',
 'Ясеневая улица',
 'Каширское шоссе',
 'Варшавское шоссе',
 'Шипиловская улица',
 '1-й Нагатинский проезд',
 'Солянский тупик',
 'Солянский тупик',
 'Сибирский проезд',
 'Нижний Таганский тупик',
 'Валовая улица',
 'Николоямская улица',
 'Николоямская улица',
 'Погодинская улица',
 'Большая Бронная улица',
 '2-я Брестская улица',
 'Профсоюзная улица',
 'Калашный переулок',
 'улица Земляной Вал',
 'Таганская площадь',
 'проезд Добролюбова',
 'улица Обручева',
 'Вспольный переулок',
 'улица Ленинская Слобода',
 'улица Ленинская Слобода',
 'улица Ленинская Слобода',
 'Дербеневская улица',
 'Проектируемый проезд N 5231',
 'Ленинский проспект',
 'Новоданиловская набережная',
 'Новорязанская улица',
 'улица Знаменка',
 'Школьная улица',
 'Чертановская улица',
 'Варшавское шоссе',
 'улица Миклухо-Маклая',
 '1-я Тверская-Ямская улица',
 'Варшавское шоссе',
 'улица Солянка',
 'Рочдельская улица',
 'Кировоградская улица',
 'Краснохолмская набережная',
 'Рочдельская улица',
 'Котляковская улица',
 'Таганская улица',
 'Славянская площадь',
 'Загорьевская улица',
 'Новолужнецкий проезд',
 'Южнобутовская улица',
 'Кировоградская улица',
 'Коровинское шоссе',
 'Суворовская площадь',
 'Тушинская улица',
 'Покровская улица',
 'Большая Серпуховская улица',
 'Николоямская улица',
 'Ленинградский проспект',
 '2-я Брестская улица',
 'Пятницкая улица',
 'улица Берзарина',
 'Ленинградский проспект',
 'Борисовский проезд',
 'Садовая-Сухаревская улица',
 'Солянский тупик',
 'Сигнальный проезд',
 'Зеленый проспект',
 'Первомайская улица',
 'Шоссейная улица',
 'Покровская улица',
 'Куликовская улица',
 'Ратная улица',
 'Киевская улица',
 '5-й Донской проезд',
 'Шипиловский проезд',
 'Булатниковский проезд',
 'улица Сергея Макеева',
 'Рочдельская улица',
 'Донская улица',
 'Киевская улица',
 'Алтуфьевское шоссе',
 'Кировоградская улица',
 'улица Льва Толстого',
 'улица Льва Толстого',
 'улица Льва Толстого',
 'Вознесенский переулок',
 'Николоямская улица',
 'Южнопортовая улица',
 'Нижегородская улица',
 'улица Юных Ленинцев',
 'Тарусская улица',
 'Краснопресненская набережная',
 'Краснопресненская набережная',
 'Бауманская улица',
 'Бауманская улица',
 'Садовническая улица',
 'Таганская площадь',
 'Шарикоподшипниковская улица',
 'Сигнальный проезд',
 'Угрешская улица',
 'Новочеркасский бульвар',
 'Новочеркасский бульвар',
 'Новочеркасский бульвар',
 'улица Перерва',
 'Жулебинский бульвар',
 'Покровская улица',
 'улица Грузинский Вал',
 'улица Грузинский Вал',
 'Дмитровское шоссе',
 'улица Лестева',
 '33-й километр Московской Кольцевой Автодороги',
 '33-й километр Московской Кольцевой Автодороги',
 'Варшавское шоссе',
 'Рочдельская улица',
 'Новорижское шоссе',
 'Новорижское шоссе',
 'Каширское шоссе',
 'Нижегородская улица']
In [50]:
# создадим таблицу с разделением адреса в таблице, полученной из внешнего источника, на столбцы
address_open_data = open_data['address'].str.split(', ', expand = True)
address_open_data.head()
Out[50]:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
0 город Москва Варшавское шоссе дом 150 строение 2 None None None None None None None None None None None None None None
1 город Москва Косинская улица дом 26А None None None None None None None None None None None None None None None
2 город Москва Гороховский переулок дом 21 None None None None None None None None None None None None None None None
3 город Москва Тагильская улица дом 4 строение 36 None None None None None None None None None None None None None None
4 город Москва Ленинградский проспект дом 73А строение 3 None None None None None None None None None None None None None None
In [51]:
# добавим в таблицу столбец с улицей объекта
open_data['street'] = address_open_data[1]
open_data.head()
Out[51]:
address adm_area district street
0 город Москва, Варшавское шоссе, дом 150, строе... Южный административный округ муниципальный округ Чертаново Южное Варшавское шоссе
1 город Москва, Косинская улица, дом 26А Восточный административный округ муниципальный округ Вешняки Косинская улица
2 город Москва, Гороховский переулок, дом 21 Центральный административный округ муниципальный округ Басманный Гороховский переулок
3 город Москва, Тагильская улица, дом 4, строени... Восточный административный округ муниципальный округ Метрогородок Тагильская улица
4 город Москва, Ленинградский проспект, дом 73А,... Северный административный округ муниципальный округ Сокол Ленинградский проспект
In [52]:
# заполним пропущенные значения административного и муниципального округов объекта общестенного питания 
for street in unnamed_streets:
    try:
        adm_area_value = open_data.query('street == @street')['adm_area'].unique()[0]
        df_new.loc[(df_new['street'] == street) & area_isna, 'adm_area'] = adm_area_value
        district_value = open_data.query('street == @street')['district'].unique()[0]
        df_new.loc[(df_new['street'] == street) & area_isna, 'district'] = district_value
    except:
        df_new.loc[(df_new['street'] == street) & area_isna, 'adm_area'] = np.nan
        df_new.loc[(df_new['street'] == street) & area_isna, 'district'] = np.nan
df_new.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 14536 entries, 0 to 14535
Data columns (total 9 columns):
 #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
 0   id               14536 non-null  int64 
 1   object_name      14536 non-null  object
 2   chain            14536 non-null  object
 3   object_type      14536 non-null  object
 4   address          14536 non-null  object
 5   number_of_seats  14536 non-null  int64 
 6   street           14536 non-null  object
 7   adm_area         14534 non-null  object
 8   district         14534 non-null  object
dtypes: int64(2), object(7)
memory usage: 1022.2+ KB

В столбцах административного и муниципального округов объекта общественного питания остались незаполненными 2 строки, удалим их.

In [53]:
# удалим строки с пропущенными значениями административного и муниципального округов
df_new.dropna(subset = ['adm_area'],
              inplace = True)
df_new = df_new.reset_index(drop = True)
df_new.isnull().sum()
Out[53]:
id                 0
object_name        0
chain              0
object_type        0
address            0
number_of_seats    0
street             0
adm_area           0
district           0
dtype: int64
In [54]:
# для удобства визуализации сократим названия административного и муниципального округов
df_new['adm_area'] = df_new['adm_area'].str.replace(' административный округ', '')
df_new['district'] = df_new['district'].str.replace('муниципальный округ ', '')
df_new.head()
Out[54]:
id object_name chain object_type address number_of_seats street adm_area district
0 151635 СМЕТАНА not_chain кафе город Москва, улица Егора Абакумова, дом 9 48 улица Егора Абакумова Северо-Восточный Ярославский
1 77874 Родник not_chain кафе город Москва, улица Талалихина, дом 2/1, корпус 1 35 улица Талалихина Центральный Таганский
2 24309 Кафе «Академия» not_chain кафе город Москва, Абельмановская улица, дом 6 95 Абельмановская улица Центральный Таганский
3 21894 ПИЦЦЕТОРИЯ chain кафе город Москва, Абрамцевская улица, дом 1 40 Абрамцевская улица Северо-Восточный Лианозово
4 119365 Кафе «Вишневая метель» not_chain кафе город Москва, Абрамцевская улица, дом 9, корпус 1 50 Абрамцевская улица Северо-Восточный Лианозово

Таблица готова для последующего анализа.

In [55]:
# выделим топ-10 улиц с наибольшим количеством объектов общественного питания
top_10_streets = df_new.groupby('street')\
                       ['id'].count()\
                       .reset_index()\
                       .sort_values(by = 'id',
                                    ascending = False)\
                       .rename(columns = {'id' : 'count'})\
                       .reset_index(drop = True)\
                       .head(10)
top_10_streets
Out[55]:
street count
0 проспект Мира 204
1 Профсоюзная улица 183
2 Ленинградский проспект 173
3 Пресненская набережная 167
4 Варшавское шоссе 162
5 Ленинский проспект 148
6 проспект Вернадского 132
7 Кутузовский проспект 114
8 Каширское шоссе 112
9 Кировоградская улица 110
In [56]:
# построим график топ-10 улиц с наибольшим количеством объектов общественного питания
fig = px.bar(top_10_streets,
             x = 'count',
             y = 'street',
             color = 'street')
fig.update_layout(title = 'Топ-10 улиц с наибольшим количеством объектов общественного питания',
                  xaxis_title = 'Количество объектов',
                  yaxis_title = 'Улица',
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Улица: %{y}')
fig.show()

Наибольшее количество объектов общественного питания Москвы находится на проспекте Мира - 204, на Профсоюзной улице размещено 183 заведения. Кроме перечисленных, более 150 объектов находятся на Ленинградском проспекте, Пресненской набережной и Варшавском шоссе.

In [57]:
# создадим список с топ-10 улиц с наибольшим количеством объектов общественного питания
top_10_streets_list = top_10_streets['street'].to_list()
top_10_streets_list
Out[57]:
['проспект Мира',
 'Профсоюзная улица',
 'Ленинградский проспект',
 'Пресненская набережная',
 'Варшавское шоссе',
 'Ленинский проспект',
 'проспект Вернадского',
 'Кутузовский проспект',
 'Каширское шоссе',
 'Кировоградская улица']
In [58]:
# создадим таблицу топ-10 улиц с наибольшим количеством объектов общественного питания с учетом административного округа
top_10_streets_area = df_new.query('street == @top_10_streets_list')\
                            .groupby(['street', 'adm_area'])\
                            ['id'].count()\
                            .reset_index()\
                            .sort_values(by = ['street', 'id'],
                                         ascending = False)\
                            .rename(columns = {'id' : 'count'})\
                            .reset_index(drop = True)
top_10_streets_area
Out[58]:
street adm_area count
0 проспект Мира Северо-Восточный 141
1 проспект Мира Центральный 63
2 проспект Вернадского Западный 117
3 проспект Вернадского Юго-Западный 15
4 Профсоюзная улица Юго-Западный 183
5 Пресненская набережная Центральный 167
6 Ленинский проспект Юго-Западный 87
7 Ленинский проспект Центральный 25
8 Ленинский проспект Западный 22
9 Ленинский проспект Южный 14
10 Ленинградский проспект Северный 173
11 Кутузовский проспект Западный 114
12 Кировоградская улица Южный 110
13 Каширское шоссе Южный 112
14 Варшавское шоссе Южный 160
15 Варшавское шоссе Юго-Западный 2
In [59]:
# посчитаем количество административных округов,
# к которым относится топ-10 улиц с наибольшим количеством объектов общественного питания
top_10_streets_area.groupby('street')\
                   ['adm_area'].nunique()\
                   .sort_values(ascending = False)
Out[59]:
street
Ленинский проспект        4
проспект Мира             2
проспект Вернадского      2
Варшавское шоссе          2
Профсоюзная улица         1
Пресненская набережная    1
Ленинградский проспект    1
Кутузовский проспект      1
Кировоградская улица      1
Каширское шоссе           1
Name: adm_area, dtype: int64
In [60]:
# построим график топ-10 улиц с наибольшим количеством объектов общественного питания с учетом административного округа
fig = px.bar(top_10_streets_area,
             x = 'count',
             y = 'street',
             color = 'adm_area',
             labels = {'adm_area' : 'Округ'})
fig.update_layout(title = 'Топ-10 улиц с наибольшим количеством объектов общественного питания',
                  xaxis_title = 'Количество объектов',
                  yaxis_title = 'Улица',
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Улица: %{y}')
fig.show()

Объекты общественного питания, находящиеся на Ленинском проспекте, размещены в 4 разных административных округах Москвы, в 2 разных административных округах размещены заведения, находящиеся на проспекте Мира, проспекте Вернадского и Варшавском шоссе.

In [61]:
# создадим таблицу топ-10 улиц с наибольшим количеством объектов общественного питания с учетом муниципального округа
top_10_streets_district = df_new.query('street == @top_10_streets_list')\
                                .groupby(['street', 'district'])\
                                ['id'].count()\
                                .reset_index()\
                                .sort_values(by = ['street', 'id'],
                                         ascending = False)\
                                .rename(columns = {'id' : 'count'})\
                                .reset_index(drop = True)
top_10_streets_district
Out[61]:
street district count
0 проспект Мира Мещанский 63
1 проспект Мира Свиблово 62
2 проспект Мира Алексеевский 51
3 проспект Мира Останкинский 20
4 проспект Мира Ростокино 7
5 проспект Мира Ярославский 1
6 проспект Вернадского Тропарево-Никулино 69
7 проспект Вернадского Раменки 32
8 проспект Вернадского Проспект Вернадского 16
9 проспект Вернадского Ломоносовский 14
10 проспект Вернадского Гагаринский 1
11 Профсоюзная улица Теплый Стан 40
12 Профсоюзная улица Черемушки 37
13 Профсоюзная улица Коньково 34
14 Профсоюзная улица Обручевский 32
15 Профсоюзная улица Академический 25
16 Профсоюзная улица Ясенево 15
17 Пресненская набережная Пресненский 167
18 Ленинский проспект Гагаринский 40
19 Ленинский проспект Обручевский 32
20 Ленинский проспект Якиманка 25
21 Ленинский проспект Тропарево-Никулино 20
22 Ленинский проспект Донской 14
23 Ленинский проспект Ломоносовский 12
24 Ленинский проспект Теплый Стан 3
25 Ленинский проспект Проспект Вернадского 2
26 Ленинградский проспект Аэропорт 65
27 Ленинградский проспект Беговой 51
28 Ленинградский проспект Хорошевский 31
29 Ленинградский проспект Сокол 26
30 Кутузовский проспект Дорогомилово 61
31 Кутузовский проспект Фили-Давыдково 53
32 Кировоградская улица Чертаново Центральное 79
33 Кировоградская улица Чертаново Северное 21
34 Кировоградская улица Чертаново Южное 10
35 Каширское шоссе Нагатино-Садовники 51
36 Каширское шоссе Москворечье-Сабурово 41
37 Каширское шоссе Орехово-Борисово Северное 14
38 Каширское шоссе Орехово-Борисово Южное 6
39 Варшавское шоссе Нагорный 41
40 Варшавское шоссе Чертаново Южное 41
41 Варшавское шоссе Донской 34
42 Варшавское шоссе Чертаново Северное 23
43 Варшавское шоссе Чертаново Центральное 13
44 Варшавское шоссе Нагатино-Садовники 8
45 Варшавское шоссе Южное Бутово 2
In [62]:
# посчитаем количество муниципальных округов,
# к которым относится топ-10 улиц с наибольшим количеством объектов общественного питания
top_10_streets_district.groupby('street')\
                       ['district'].nunique()\
                       .sort_values(ascending = False)
Out[62]:
street
Ленинский проспект        8
Варшавское шоссе          7
проспект Мира             6
Профсоюзная улица         6
проспект Вернадского      5
Ленинградский проспект    4
Каширское шоссе           4
Кировоградская улица      3
Кутузовский проспект      2
Пресненская набережная    1
Name: district, dtype: int64
In [63]:
# построим график топ-10 улиц с наибольшим количеством объектов общественного питания с учетом муниципального округа
fig = px.bar(top_10_streets_district,
             x = 'count',
             y = 'street',
             color = 'district',
             labels = {'district' : 'Муниципальный округ'})
fig.update_layout(title = 'Топ-10 улиц с наибольшим количеством объектов общественного питания',
                  xaxis_title = 'Количество объектов',
                  yaxis_title = 'Улица',
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Улица: %{y}')
fig.show()

Объекты общественного питания, находящиеся на Ленинском проспекте, размещены в 8 разных муниципальных округах Москвы, в 7 разных муниципальных округах размещены заведения, находящиеся на Варшавском шоссе, в 6 - на проспекте Мира и Профсоюзной улице.

Учитывая достаточно большую протяженность улиц, что приводит к тому, что они могут проходить через разные административные и муниципальные округа, анализ размещения объектов общественного питания целесообразнее проводить по муниципальным округам ввиду их более компактного расположения, либо по улицам с учетом принадлежности их частей конкретным муниципальным округам.

In [64]:
# выделим топ-10 муниципальных округов с наибольшим количеством объектов общественного питания
top_10_district = df_new.groupby('district')\
                        ['id'].count()\
                        .reset_index()\
                        .sort_values(by = 'id',
                                     ascending = False)\
                        .rename(columns = {'id' : 'count'})\
                        .reset_index(drop = True)\
                        .head(10)
top_10_district
Out[64]:
district count
0 Тверской 778
1 Пресненский 722
2 Басманный 634
3 Даниловский 467
4 Замоскворечье 390
5 Хамовники 376
6 Таганский 362
7 Мещанский 351
8 Арбат 269
9 Хорошевский 257
In [65]:
# построим график топ-10 муниципальных округов с наибольшим количеством объектов общественного питания
fig = px.bar(top_10_district,
             x = 'count',
             y = 'district',
             color = 'district')
fig.update_layout(title = 'Топ-10 муниципальных округов с наибольшим количеством объектов общественного питания',
                  xaxis_title = 'Количество объектов',
                  yaxis_title = 'Муниципальный округ',
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Округ: %{y}')
fig.show()

Наибольшее количество объектов общественного питания Москвы находится в Тверском (778) и Пресненском (722) муниципальных округах. Кроме перечисленных, более 400 заведений в Басманном и Даниловском муниципальных округах.

In [66]:
# выделим топ-10 улиц с наибольшим количеством объектов общественного питания
# с учетом принадлежности их частей конкретным муниципальным округам
top_10_part_streets_district = df_new.groupby(['street', 'district'])\
                                     ['id'].count()\
                                     .reset_index()\
                                     .sort_values(by = 'id',
                                                  ascending = False)\
                                     .rename(columns = {'id' : 'count'})\
                                     .reset_index(drop = True)\
                                     .head(10)
top_10_part_streets_district
Out[66]:
street district count
0 Пресненская набережная Пресненский 167
1 Ходынский бульвар Хорошевский 102
2 улица Новый Арбат Арбат 92
3 улица Ленинская Слобода Даниловский 89
4 улица Сущевский Вал Марьина Роща 82
5 Пятницкая улица Замоскворечье 80
6 Кировоградская улица Чертаново Центральное 79
7 улица Покровка Басманный 77
8 улица Арбат Арбат 77
9 Ленинградское шоссе Войковский 72
In [67]:
# построим график топ-10 улиц с наибольшим количеством объектов общественного питания 
# с учетом принадлежности их частей конкретным муниципальным округам
fig = px.bar(top_10_part_streets_district,
             x = 'count',
             y = 'street',
             color = 'district',
             labels = {'district' : 'Муниципальный округ'})
fig.update_layout(title = 'Топ-10 улиц с наибольшим количеством объектов общественного питания\
<br>с учетом принадлежности их частей конкретным муниципальным округам',
                  xaxis_title = 'Количество объектов',
                  yaxis_title = 'Улица',
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Улица: %{y}')
fig.show()

Наибольшее количество объектов общественного питания Москвы с учетом принадлежности частей улиц конкретным муниципальным округам находится на Пресненской набережной, которая целиком расположена в Пресненском муниципальном округе (167), и Ходынском бульваре, также целиком расположенном в Хорошевском муниципальном округе (102, однако как уже отмечалось ранее, 95 из них находятся по одному адресу). На двух улицах муниципального округа Арбат - Новый Арбат и Арбат - расположено в сумме 169 заведений общественного питания.

Определение числа улиц с одним объектом общественного питания, а также, в каких районах Москвы находятся эти улицы

In [68]:
# определим количество улиц с одним объектом общественного питания
streets_one_object = df_new.groupby('street')\
                           .filter(lambda x: len(x) == 1)\
                           .groupby(['street', 'adm_area', 'district'])\
                           ['id'].count()\
                           .reset_index()\
                           .rename(columns = {'id' : 'count'})\
                           .reset_index(drop = True)
len(streets_one_object)
Out[68]:
537

Из всех улиц Москвы с объектами общественного питания на 537 из них находится всего по одному заведению.

In [69]:
# определим количество улиц с одним объектом общественного питания по административным округам
one_object_area = streets_one_object.groupby('adm_area')\
                                    ['count'].count()\
                                    .reset_index()\
                                    .sort_values(by = 'count',
                                                ascending = False)\
                                    .reset_index(drop = True)                                           
one_object_area
Out[69]:
adm_area count
0 Центральный 169
1 Северо-Восточный 65
2 Восточный 64
3 Юго-Восточный 54
4 Северный 53
5 Западный 43
6 Южный 32
7 Северо-Западный 29
8 Юго-Западный 28
In [70]:
# построим график количества улиц с одним объектом общественного питания по административным округам
fig = px.bar(one_object_area,
             x = 'count',
             y = 'adm_area',
             color = 'adm_area')
fig.update_layout(title = 'Количество улиц с одним объектом общественного питания по административным округам',
                  xaxis_title = 'Количество улиц',
                  yaxis_title = 'Округ',
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Округ: %{y}')
fig.show()

Наибольшее количество улиц с одним объектом общественного питания в Центральном административном округе - 169. Вероятнее всего, это связано с небольшой продолжительностью улиц в этом округе и большим их количеством.

In [71]:
# выделим топ-10 муниципальных округов с наибольшим количеством улиц с одним объектом общественного питания
top_10_one_object_district = streets_one_object.groupby('district')\
                                               ['count'].count()\
                                               .reset_index()\
                                               .sort_values(by = 'count',
                                                            ascending = False)\
                                               .reset_index(drop = True)\
                                               .head(10)
top_10_one_object_district
Out[71]:
district count
0 Таганский 27
1 Хамовники 26
2 Басманный 22
3 Тверской 20
4 Пресненский 19
5 Марьина Роща 17
6 Сокольники 15
7 Лефортово 12
8 Мещанский 12
9 Соколиная Гора 12
In [72]:
# построим график топ-10 муниципальных округов с наибольшим количеством улиц с одним объектом общественного питания
fig = px.bar(top_10_one_object_district,
             x = 'count',
             y = 'district',
             color = 'district')
fig.update_layout(title = 'Топ-10 муниципальных округов с наибольшим количеством улиц\
<br>с одним объектом общественного питания',
                  xaxis_title = 'Количество улиц',
                  yaxis_title = 'Муниципальный округ',
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Округ: %{y}')
fig.show()

Наибольшее количество улиц с одним объектом общественного питания в Таганском (27), Басманном (22) и Тверском (20) муниципальных округах, а также муниципальном округе Хамовники (26). 6 из 10 муниципальных округов из топ-10 округов с наибольшим количеством заведений попали в топ-10 округов с наибольшим количеством улиц с одним объектом общественного питания. Вероятнее всего, это связано с небольшой продолжительностью улиц в этих округах и большим их количеством.

Анализ распределения количества посадочных мест для улиц с большим количеством объектов общественного питания

In [73]:
# создадим таблицу со средним количеством посадочных мест в объектах общественного питания на улицах с наибольшим их числом 
top_10_streets_seats_mean = df_new.query('street == @top_10_streets_list')\
                                  .groupby('street')\
                                  ['number_of_seats'].median()\
                                  .reset_index()\
                                  .rename(columns = {'number_of_seats' : 'number_of_seats_mean'})\
                                  .sort_values(by = 'number_of_seats_mean',
                                               ascending = False)\
                                  .reset_index(drop = True) 
top_10_streets_seats_mean    
Out[73]:
street number_of_seats_mean
0 проспект Мира 46.50
1 Ленинский проспект 45.00
2 Кутузовский проспект 40.00
3 Ленинградский проспект 40.00
4 проспект Вернадского 40.00
5 Варшавское шоссе 30.00
6 Кировоградская улица 30.00
7 Пресненская набережная 30.00
8 Каширское шоссе 25.00
9 Профсоюзная улица 24.00
In [74]:
# построим график распределения количества посадочных мест в объектах общественного питания
# на улицах с наибольшим их числом
fig = px.box(df_new.query('street == @top_10_streets_list'),
             x = 'number_of_seats',
             y = 'street',
             color = 'street')
fig.update_layout(title = 'Распределение количества посадочных мест в объектах общественного питания\
<br>на улицах с наибольшим их числом',
                  xaxis_title = 'Количество посадочных мест',
                  yaxis_title = 'Улица',
                  xaxis = dict(range = [-10, 400]),
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Улица: %{y}')
fig.show()

Наибольшее среднее количество посадочных мест (медиана) среди топ-10 улиц с наибольшим числом объектов общественного питания у проспекта Мира (46,5) и Ленинского проспекта (45), наименьшее - у Профсоюзной улицы (24) и Каширского шоссе (25). Наибольший разброс количества посадочных мест характерен для Кутузовского проспекта, Каширского шоссе и проспекта Мира.

Как отмечалось ранее, учитывая достаточно большую протяженность улиц, что приводит к тому, что они могут проходить через разные административные и муниципальные округа, анализ целесообразнее проводить по муниципальным округам ввиду их более компактного расположения, либо по улицам с учетом принадлежности их частей конкретным муниципальным округам.

In [75]:
# создадим список с топ-10 районов с наибольшим количеством объектов общественного питания
top_10_district_list = top_10_district['district'].to_list()
top_10_district_list
Out[75]:
['Тверской',
 'Пресненский',
 'Басманный',
 'Даниловский',
 'Замоскворечье',
 'Хамовники',
 'Таганский',
 'Мещанский',
 'Арбат',
 'Хорошевский']
In [76]:
# создадим таблицу со средним количеством посадочных мест
# в объектах общественного питания в муниципальных округах с наибольшим их числом 
top_10_district_seats_mean = df_new.query('district == @top_10_district_list')\
                                   .groupby('district')\
                                   ['number_of_seats'].median()\
                                   .reset_index()\
                                   .rename(columns = {'number_of_seats' : 'number_of_seats_mean'})\
                                   .sort_values(by = 'number_of_seats_mean',
                                                ascending = False)\
                                   .reset_index(drop = True) 
top_10_district_seats_mean    
Out[76]:
district number_of_seats_mean
0 Тверской 50.00
1 Таганский 45.00
2 Замоскворечье 41.50
3 Арбат 40.00
4 Мещанский 40.00
5 Пресненский 40.00
6 Хамовники 40.00
7 Басманный 38.00
8 Даниловский 20.00
9 Хорошевский 20.00
In [77]:
# построим график распределения количества посадочных мест в объектах общественного питания
# в муниципальных округах с наибольшим их числом
fig = px.box(df_new.query('district == @top_10_district_list'),
             x = 'number_of_seats',
             y = 'district',
             color = 'district')
fig.update_layout(title = 'Распределение количества посадочных мест в объектах общественного питания\
<br>в муниципальных округах с наибольшим их количеством',
                  xaxis_title = 'Количество посадочных мест',
                  yaxis_title = 'Муниципальный округ',
                  xaxis = dict(range = [-10, 400]),
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 70, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Округ: %{y}')
fig.show()

Наибольшее среднее количество посадочных мест (медиана) среди топ-10 муниципальных округов с наибольшим числом объектов общественного питания у Тверского (50) и Таганского (45) округов, наименьшее - у Хорошевского и Даниловского (по 20) округов. Наибольший разброс количества посадочных мест характерен для Тверского, Таганского и Мещанского муниципальных округов.

In [78]:
# создадим список с топ-10 улиц с наибольшим количеством объектов общественного питания
# с учетом принадлежности их частей конкретным муниципальным округам
top_10_part_streets_list = top_10_part_streets_district['street'].to_list()
top_10_part_district_list = top_10_part_streets_district['district'].to_list()
top_10_part_streets_list
Out[78]:
['Пресненская набережная',
 'Ходынский бульвар',
 'улица Новый Арбат',
 'улица Ленинская Слобода',
 'улица Сущевский Вал',
 'Пятницкая улица',
 'Кировоградская улица',
 'улица Покровка',
 'улица Арбат',
 'Ленинградское шоссе']
In [79]:
# создадим таблицу со средним количеством посадочных мест в объектах общественного питания 
# на улицах с наибольшим их числом с учетом принадлежности их частей конкретным муниципальным округам
top_10_part_streets_district_seats_mean = df_new.query('street == @top_10_part_streets_list\
                                                       & district == @top_10_part_district_list')\
                                                .groupby(['street',
                                                          'district'])\
                                                ['number_of_seats'].median()\
                                                .reset_index()\
                                                .rename(columns = {'number_of_seats' : 'number_of_seats_mean'})\
                                                .sort_values(by = 'number_of_seats_mean',
                                                             ascending = False)\
                                                .reset_index(drop = True) 
top_10_part_streets_district_seats_mean
Out[79]:
street district number_of_seats_mean
0 улица Арбат Арбат 48.00
1 Пятницкая улица Замоскворечье 46.50
2 улица Покровка Басманный 42.00
3 улица Новый Арбат Арбат 36.00
4 Ленинградское шоссе Войковский 30.00
5 Пресненская набережная Пресненский 30.00
6 Кировоградская улица Чертаново Центральное 24.00
7 Ходынский бульвар Хорошевский 10.00
8 улица Ленинская Слобода Даниловский 10.00
9 улица Сущевский Вал Марьина Роща 10.00
In [80]:
# построим график распределения количества посадочных мест в объектах общественного питания
# на улицах с наибольшим их числом с учетом принадлежности их частей конкретным муниципальным округам
fig = px.box(df_new.query('street == @top_10_part_streets_list & district == @top_10_part_district_list'),
             x = 'number_of_seats',
             y = 'street',
             color = 'street')
fig.update_layout(title = 'Распределение количества посадочных мест в объектах общественного питания\
<br>на улицах с наибольшим их числом с учетом принадлежности\
<br>их частей конкретным муниципальным округам',
                  xaxis_title = 'Количество посадочных мест',
                  yaxis_title = 'Улица',
                  xaxis = dict(range = [-10, 400]),
                  showlegend = False,
                  margin = dict(l = 0, r = 0, t = 100, b = 0))
fig.update_traces(hovertemplate = 'Количество: %{x}<br>Улица: %{y}')
fig.show()

Наибольшее среднее количество посадочных мест (медиана) среди топ-10 улиц с наибольшим числом объектов общественного питания с учетом принадлежности их частей конкретным муниципальным округам у улицы Арбат (48), Пятницкой улицы (46,5) и улицы Покровка (42), наименьшее - у Ходынского бульвара, улиц Ленинская Слобода и Сущевский вал (по 10), вероятнее всего это связано со значительным количеством заведений в крупных торговых центрах с небольшим количеством посадочных мест. Наибольший разброс количества посадочных мест характерен для улиц Новый Арбат и Арбат, а также Пятницкой и Кировоградской улиц.

Подготовка презентации исследования для инвесторов

Общий вывод

  1. В Москве самым популярным видом объекта общественного питания является кафе, всего имеется 6099 таких заведений (39,7% от общего количества объектов). Достаточно большую долю на рынке занимают столовые, рестораны и фаст-фуды, которая составляет соответственно 16,8% (2587 заведений), 14,9% (2285 заведений) и 12,5% (1923 заведения). Менее 3% доля от общего количества объектов у кулинарий, закусочных и кафетериев.
  2. Преобладают несетевые объекты общественного питания, их доля от общего количества заведений составляет 80,7% (количество - 12398). Объектов, принадлежащих различным сетям, - 2968 (19,3%).
  3. В абсолютном выражении среди сетевых объектов общественного питания больше всего кафе, вероятнее всего из-за большей распространенности заведений этого вида, однако, при изучении относительных показателей картина немного иная. Наибольшая доля сетевых заведений у фаст-фудов (41,1%) и кулинарий (28,6%). У самого распространенного вида объектов общественного питания - кафе - доля сетевых заведений составляет 22,3%. Наименьшее и абсолютное количество сетевых заведений, и доля от всех объектов данного вида у столовых и буфетов.
  4. Среднее количество посадочных мест в сетевых объектах общественного питания 53, медианное - 40. Для 75% сетевых заведений число посадочных мест не превысило 72. Для несетевых заведений характерен больший разброс значений количества посадочных мест, при этом при одинаковых медианных значениях количества мест у сетевых и несетевых объектов, среднее арифиметическое у несетевых заведений значительно выше. Исходя из проведенного аналиа, можно утверждать, что для сетевых объектов общественного питания характерно много заведений с небольшим количеством посадочных мест в каждом, и мало заведений с большим числом посадочных мест в каждом.
  5. Для каждого из видов объектов общественного питания характерна следующая закономерность: имеется небольшое количество заведений с большим числом посадочных мест и большое количество объектов с их небольшим числом. Наибольшее количество посадочных мест из видов объектов общественного питания у столовых, у них же наибольший разброс этих значений. У закусочных и кулинарий более половины заведений не имеет посадочных мест, а у кафетериев и фаст-фудов посадочных мест не имеют более 25% объектов.
  6. Наибольшее среднее количество посадочных мест у столовых - 103, и ресторанов - 80. У самого распространенного вида заведений - кафе - среднее количество посадочных мест достаточно небольшое - 30. У объектов с самой большой долей сетевых заведений - фаст-фудов - среднее количество посадочных мест совсем мало - 5. У закусочных и кулинарий среднее количество посадочных мест равно 0.
  7. Наибольшее количество объектов общественного питания Москвы находится на проспекте Мира - 204, на Профсоюзной улице размещено 183 заведения. Кроме перечисленных, более 150 объектов находятся на Ленинградском проспекте, Пресненской набережной и Варшавском шоссе. Вместе с тем, в связи с достаточно большой протяженностью улиц, они проходят через разные административные и муниципальные округа. Так, напимер, объекты общественного питания, находящиеся на Ленинском проспекте, размещены в 4 разных административных и 8 разных муниципальных округах Москвы, в 2 разных административных и 7 разных муниципальных округах размещены заведения, находящиеся на Варшавском шоссе.
    Учитывая изложенное, анализ размещения объектов общественного питания целесообразнее проводить по муниципальным округам ввиду их более компактного расположения, либо по улицам с учетом принадлежности их частей конкретным муниципальным округам.
    Так, наибольшее количество объектов общественного питания находится в Тверском (778) и Пресненском (722) муниципальных округах. Кроме перечисленных, более 400 заведений в Басманном и Даниловском муниципальных округах.
    Наибольшее количество объектов общественного питания с учетом принадлежности частей улиц конкретным муниципальным округам находится на Пресненской набережной, которая целиком расположена в Пресненском муниципальном округе (167), и Ходынском бульваре, также целиком расположенном в Хорошевском муниципальном округе (102, однако как уже отмечалось ранее, 95 из них находятся по одному адресу). На двух улицах муниципального округа Арбат - Новый Арбат и Арбат - расположено в сумме 169 заведений общественного питания.
  8. Из всех улиц Москвы с объектами общественного питания на 537 из них находится всего по одному заведению. Наибольшее количество улиц с одним объектом общественного питания в Центральном административном округе - 169, Таганском (27), Басманном (22) и Тверском (20) муниципальных округах, а также муниципальном округе Хамовники (26). 6 из 10 муниципальных округов из топ-10 округов с наибольшим количеством заведений попали в топ-10 округов с наибольшим количеством улиц с одним объектом общественного питания. Вероятнее всего, это связано с небольшой продолжительностью улиц в этих округах и большим их количеством.
  9. Наибольшее среднее количество посадочных мест среди топ-10 улиц с наибольшим числом объектов общественного питания у проспекта Мира (46,5) и Ленинского проспекта (45), наименьшее - у Профсоюзной улицы (24) и Каширского шоссе (25). Наибольший разброс количества посадочных мест характерен для Кутузовского проспекта, Каширского шоссе и проспекта Мира.
    Наибольшее среднее количество посадочных мест среди топ-10 муниципальных округов с наибольшим числом объектов общественного питания у Тверского (50) и Таганского (45) округов, наименьшее - у Хорошевского и Даниловского (по 20) округов. Наибольший разброс количества посадочных мест характерен для Тверского, Таганского и Мещанского муниципальных округов.
    Наибольшее среднее количество посадочных мест среди топ-10 улиц с наибольшим числом объектов общественного питания с учетом принадлежности их частей конкретным муниципальным округам у улицы Арбат (48), Пятницкой улицы (46,5) и улицы Покровка (42), наименьшее - у Ходынского бульвара, улиц Ленинская Слобода и Сущевский вал (по 10), вероятнее всего это связано со значительным количеством заведений в крупных торговых центрах с небольшим количеством посадочных мест. Наибольший разброс количества посадочных мест характерен для улиц Новый Арбат и Арбат, а также Пятницкой и Кировоградской улиц.

Рекомендации

Рекомендуется открыть заведение:

  • вида кафе, так как это самый популярный тип объекта общественного питания;
  • на первоначальном этапе несетевое с перспективой вложения инвестиций и развития соответствующей сети;
  • с количеством посадочных мест около 30, так как это среднее количество мест для объектов вида кафе;
  • в Центральном административном округе в Тверском, Пресненском муниципальных округах либо муниципальном округе Арбат, на Пятницкой улице либо улице Покровка, как самых популярных местах для рынка общественного питания.

При развитии сети обратить внимание на возможность размещения заведений в крупных торговых центрах вне вышеуказанного района.